package com.zone.domain.strategy.service.rule.chain;

import com.zone.domain.strategy.model.valobj.RuleActionEnum;
import com.zone.types.utils.CollectionUtils;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

/**
 * @author: zongzi
 * @description: 抽奖过滤器链，负责组装处理器链与委派请求给处理器
 * @date: 2024/6/3
 */
@Slf4j
@Service
public class RaffleRuleFilterChain {
    // 根节点过滤器
    private IRaffleRuleFilter rootFilter;

    public RaffleRuleFilterChain(List<AbstractRaffleRuleFilter> filters) {
        // 在各个具体的过滤器中使用@Order指定顺序，未添加的该注解的排序到尾部
        // 未配置抽奖过滤器，不设置过滤器
        if (CollectionUtils.isNotEmpty(filters)) {
            // 组装各个处理器的下一个处理器
            for (int i = 0; i < filters.size(); i++) {
                // 首个过滤器作为根过滤器
                if (i == 0) {
                    rootFilter = filters.get(0);
                }
                // 最后一个filter没有下一个处理器
                if (i == filters.size() - 1) {
                    break;
                }
                AbstractRaffleRuleFilter currentFilter = filters.get(i);
                AbstractRaffleRuleFilter nextFilter = filters.get(i + 1);
                currentFilter.setNextFilter(nextFilter);
            }
        }
    }

    /**
     * 将请求派发到各个处理器链
     *
     * @param strategyId 策略id
     * @param userId     用户id
     * @param ruleModels 规则模型
     * @return
     */
    public RaffleRuleFilterChain.StrategyAwardVO doFilter(Long strategyId, String userId, List<String> ruleModels) {
        if (Objects.isNull(rootFilter)) {
            // 没有配置过滤器则放行
            return StrategyAwardVO.allow();
        }
        return rootFilter.doFilter(strategyId, userId, ruleModels);
    }


    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class StrategyAwardVO {
        /** 奖品id */
        private Integer awardId;
        /** 奖品配置值（如黑名单处理器，会将黑名单积分(1,10)透传过来） */
        private String awardConfig;
        /** 拦截/放行请求 */
        private RuleActionEnum ruleAction;

        // 默认放行对象
        public static StrategyAwardVO allow() {
            StrategyAwardVO allowVo = new StrategyAwardVO();
            allowVo.setRuleAction(RuleActionEnum.ALLOW);
            return allowVo;
        }
    }
}
